#include "buffer.h"
#include "errhandle.h"
#include "memrec.h"

size_t tBuffer::Copy(size_t offset, PBYTE data, size_t data_size)
{
	assert(pBuf != NULL && offset < size &&
			(size - offset) >= data_size);
	if (pBuf != NULL && offset < size  && 
		(size - offset) >= data_size)
	{
		// do the safe memory copy.
		memcpy(pBuf + offset, data, data_size);
		return data_size;
	}
	else
	{
		throw GeneralException(E_MEMCOPY_OVERFLOW);
	}
}

size_t tBuffer::Copy(const tBuffer & buf, const char * file, int line)
{
	DeAlloc();
	_Alloc(buf.size, file, line);
	return Copy(0, buf.pBuf, buf.size);	
}

size_t tBuffer::Copy(size_t offset, tBuffer & buf)
{
	return Copy(offset, buf.pBuf, buf.size);
}

size_t tBuffer::_Alloc(size_t s, const char * file, int line)
{
	assert(s > 0);
	assert(pBuf == NULL);
	if (s <= 0 || pBuf != NULL)
		throw GeneralException(E_MEMALLOC_AGAIN);
	pBuf = DBG_ALLOC(file, line) BYTE[s];
	assert(pBuf != 0);
	if (pBuf == 0)
	{
		throw GeneralException(E_MEMALLOC_FAIL);
	}
	attached = true;
	size = s;
	return s;
}

void tBuffer::DeAlloc()
{
	if (pBuf != 0)
		delete[] pBuf;
	size = 0;
	pBuf = 0;
	attached = false;
}

void tBuffer::DeAllocIfAttached()
{
	if (attached == false)
	{
		deref();
		return;
	}
	else
		DeAlloc();
}

void tBuffer::Dump(size_t offset, int len, TCHAR* fn, int flag)
{
	TCHAR mode[4];
	if (flag == 0)
		lstrcpy(mode, _T("ab"));
	else
		lstrcpy(mode, _T("wb"));
#ifdef _UNICODE
	FILE * fd = NULL;
	_wfopen_s(&fd, fn, mode);
#else
	FILE * fd = fopen(fn, mode);
#endif
	fwrite(pBuf + offset, 1, len, fd);
	fclose(fd);
}

void tStreamBuffer::GetData(PBYTE pData, size_t _size)
{
	if (usedsize + _size <= size)
	{
		memcpy(pData, pBuf+usedsize, _size);
		usedsize += _size;
	}
	else
	{
		assert(false);
		throw GeneralException(E_MEMREAD_OVERFLOW);
	}
}
